package com.jrx.anytxn.reporting.service.impl;

import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.exception.TxnRuntimeException;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.common.uitl.FileUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.customer.constant.CustomerConstant;
import com.jrx.anytxn.customer.entity.CmCustomerAddressInfo;
import com.jrx.anytxn.customer.entity.CmCustomerContactInfo;
import com.jrx.anytxn.customer.entity.CmCustomerFirstLevel;
import com.jrx.anytxn.customer.entity.CmCustomerSecondLevel;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerAddressInfoMapper;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerContactInfoMapper;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerSecondLevelMapper;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.param.dto.system.SystemParameterRes;
import com.jrx.anytxn.param.entity.BtBatchStatus;
import com.jrx.anytxn.param.entity.PrAmortMethod;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.entity.PrProductTable;
import com.jrx.anytxn.param.mapper.ext.ExtBtBatchStatusMapper;
import com.jrx.anytxn.param.mapper.ext.ExtPrChannelTableMapper;
import com.jrx.anytxn.param.service.product.IAmortMethodService;
import com.jrx.anytxn.param.service.product.IProductTableService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.param.service.system.ISystemParameterService;
import com.jrx.anytxn.reporting.constant.ReportingConstant;
import com.jrx.anytxn.reporting.service.ILSFileService;
import com.jrx.anytxn.reporting.service.ILSSecondFileService;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.entity.*;
import com.jrx.anytxn.transaction.mapper.ext.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;

/**
 * 临商第二代征信文件处理实现类
 *
 * @author liuyang
 * @date 2021-04-26
 */
@Service
public class LSSecondFileServiceImpl implements ILSSecondFileService {

    private static final Logger logger = LoggerFactory.getLogger(LSSecondFileServiceImpl.class);

    @Autowired
    private ILSFileService iLSFileService;

    @Autowired
    private ICustomerService customerService;

    @Resource
    private ExtCmCustomerAddressInfoMapper extCmCustomerAddressInfoMapper;

    @Resource
    private ExtAmLoanAccountInfoMapper extAmLoanAccountInfoMapper;

    @Resource
    private ExtAmLoanMainInfoMapper extAmLoanMainInfoMapper;

    @Resource
    private ExtAmAccountMainInfoMapper extAmAccountMainInfoMapper;

    @Resource
    private ExtAmRepaymentPlanInfoMapper extAmRepaymentPlanInfoMapper;

    @Autowired
    private IOrganizationTableService organizationTableService;

    @Autowired
    private IProductTableService productTableService;

    @Resource
    private ExtAmInterestAccrualInfoMapper extAmInterestAccrualInfoMapper;

    @Resource
    private ExtTlPaymentAllocationLogMapper extTlPaymentAllocationLogMapper;

    @Autowired
    private IAmortMethodService amortMethodService;

    @Resource
    private ExtTlLoanClassifyChangeMapper extTlLoanClassifyChangeMapper;

    @Resource
    private ExtBtBatchStatusMapper extBtBatchStatusMapper;

    @Resource
    private ExtCmCustomerSecondLevelMapper extCmCustomerSecondLevelMapper;

    @Autowired
    private ISystemParameterService systemParameterService;

    @Resource
    private ExtCmCustomerContactInfoMapper extCmCustomerContactInfoMapper;

    @Resource
    private ExtPrChannelTableMapper extPrChannelTableMapper;

    /**
     * 生成个人借据信息
     *
     * @param loanId
     * @return String
     * @author liuyang
     * @date 2021-04-26
     */
    @Override
    public String createLSSecondAccountFileMessage(String loanId) throws TxnException {

        logger.debug("临商二代征信贷款借据信息文件生成，订单账户信息[{}]", loanId);

        AmLoanAccountInfo amLoanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanIdForBatch(loanId);
        AmLoanMainInfo amLoanMainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(amLoanAccountInfo.getLoanId(),
                amLoanAccountInfo.getTenantId());

        // 逾期余额计算
        BigDecimal overdueBalance = BigDecimal.ZERO;
        List<AmAccountMainInfo> amAccountMainInfos = extAmAccountMainInfoMapper.selectAccounts(amLoanMainInfo.getLoanId(),
                Arrays.asList(TransBizConstant.ACCOUNT_TYPE_06), amLoanMainInfo.getCustomerId(), amLoanMainInfo.getTenantId(),
                Arrays.asList(TransBizConstant.ACCOUNT_STATUS_2));
        if (!CollectionUtils.isEmpty(amAccountMainInfos)) {
            overdueBalance = overdueBalance.add(amAccountMainInfos.stream().map(AmAccountMainInfo::getCurrBalance).reduce(BigDecimal.ZERO, BigDecimal::add));
        }

        // 欠息余额计算 截止到目前所有的欠息余额(未还的利息+未还的罚息+未还的复利+每日累计罚息+每日累计的复利)，未到期每日产生的利息不计。
        BigDecimal interest = BigDecimal.ZERO;
        interest = interest.add(amLoanAccountInfo.getInterestBalance()).add(amLoanAccountInfo.getPenaltyBalance())
                .add(amLoanAccountInfo.getCompoundBalance()).add(amLoanAccountInfo.getAccruedPenalty()).add(amLoanAccountInfo.getAccruedCompound());

        // 最早逾期日期
        String overdueDateStr = "";
        if (TransBizConstant.LOAN_STATUS_2.equals(amLoanAccountInfo.getAccountStatus())) {
            List<AmRepaymentPlanInfo> amRepaymentPlanInfos =
                    extAmRepaymentPlanInfoMapper.selectByLoanIdAndStatus(amLoanMainInfo.getLoanId(),
                            Arrays.asList(TransBizConstant.LOAN_PLAN_STATUS_2), amLoanMainInfo.getCustomerId(),
                            amLoanMainInfo.getTenantId());
            if (!CollectionUtils.isEmpty(amRepaymentPlanInfos)) {
                AmRepaymentPlanInfo amRepaymentPlanInfo =
                        amRepaymentPlanInfos.stream().min(Comparator.comparing(AmRepaymentPlanInfo::getBillingTenor)).get();
                overdueDateStr = DateUtils.format(amRepaymentPlanInfo.getPaymentDueDate(), DateUtils.DATE_PATTERN);
            }
        }

        // 获取客户一级信息
        CmCustomerFirstLevel cmCustomerFirstLevel = customerService.getFirstLevelByCondition(amLoanMainInfo.getCustomerId(), amLoanMainInfo.getOrganizationId(), amLoanMainInfo.getTenantId());

        // 获取机构信息
        PrOrganizationTable organizationTable = organizationTableService.findByOrId(amLoanMainInfo.getOrganizationId(), amLoanMainInfo.getTenantId());

        // 还款方式
        PrAmortMethod amortMethod = amortMethodService.findByChargerOptionAndId(amLoanMainInfo.getAmortMethodTableId(), amLoanMainInfo.getOrganizationId(), amLoanMainInfo.getTenantId());
        String chargeOption = iLSFileService.getICRCode("CHARGEOPTION", amortMethod.getChargeOption());

        // 剩余还款期数 不包含以前逾期期数
        int remRepPrd = amLoanMainInfo.getTotalTenor();
        if (amLoanAccountInfo.getCastTenor() != null) {
            remRepPrd = remRepPrd - amLoanAccountInfo.getCastTenor() + 1;
            // 如果是最后一期，且最后一期已逾期或者结清，则剩余还款期数为0
            if (amLoanMainInfo.getTotalTenor().equals(amLoanAccountInfo.getCastTenor())) {
                AmRepaymentPlanInfo amRepaymentPlanInfo = extAmRepaymentPlanInfoMapper.selectByLoanIdAndTenor(amLoanMainInfo.getCustomerId(), amLoanMainInfo.getTenantId(), amLoanMainInfo.getChannel(), amLoanMainInfo.getLoanId(), amLoanAccountInfo.getCastTenor());
                if ((amRepaymentPlanInfo != null && TransBizConstant.LOAN_PLAN_STATUS_2.equals(amRepaymentPlanInfo.getPlanStatus())) ||
                        Arrays.asList(TransBizConstant.LOAN_STATUS_7, TransBizConstant.LOAN_STATUS_8).contains(amLoanAccountInfo.getAccountStatus())) {
                    remRepPrd = 0;
                }
            }
        }

        // 五级分类认定日期
        String fiveCateAdjDate = DateUtils.format(amLoanMainInfo.getPostingDate(), DateUtils.DATE_PATTERN);
        TlLoanClassifyChange tlLoanClassifyChange = extTlLoanClassifyChangeMapper.selectLastByLoanId(amLoanAccountInfo.getTenantId(), amLoanAccountInfo.getCustomerId(), amLoanAccountInfo.getLoanId());
        if (tlLoanClassifyChange!=null) {
            fiveCateAdjDate = DateUtils.format(DateUtils.parseDate(tlLoanClassifyChange.getBusinessDate(), DateUtils.DATE_PATTERN_ANOTHER), DateUtils.DATE_PATTERN);
        }

        StringBuilder sb = new StringBuilder();
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(amLoanMainInfo.getLoanId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 借据流水号
        sb.append(amLoanMainInfo.getCustomerId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 客户号
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(amLoanMainInfo.getContractId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 合同号
        sb.append(chargeOption).append(ReportingConstant.SEPARATOR_LS_SECOND);// 还款方式
        sb.append("03").append(ReportingConstant.SEPARATOR_LS_SECOND);// 还款频率 03-月
        sb.append(amLoanMainInfo.getTotalTenor()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 还款期数
        sb.append(remRepPrd).append(ReportingConstant.SEPARATOR_LS_SECOND);// 剩余还款期数
        sb.append(DateUtils.format(amLoanMainInfo.getPostingDate(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 开户日期
        sb.append(amLoanMainInfo.getLastPaymentDate()==null ? "" : DateUtils.format(amLoanMainInfo.getLastPaymentDate(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 到期日期
        sb.append("CNY").append(ReportingConstant.SEPARATOR_LS_SECOND);// 币种
        sb.append(amLoanMainInfo.getLoanAmount()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 借款金额
        sb.append(amLoanAccountInfo.getRemainPrincipal() != null ? amLoanAccountInfo.getRemainPrincipal() : BigDecimal.ZERO).append(ReportingConstant.SEPARATOR_LS_SECOND);// 余额
        sb.append(amLoanAccountInfo.getRemainPrincipal() != null ? amLoanAccountInfo.getRemainPrincipal().subtract(overdueBalance) : BigDecimal.ZERO).append(ReportingConstant.SEPARATOR_LS_SECOND);// 正常本金余额
        sb.append(overdueBalance).append(ReportingConstant.SEPARATOR_LS_SECOND);// 逾期本金余额
        sb.append(interest).append(ReportingConstant.SEPARATOR_LS_SECOND);// 利息
        sb.append(overdueDateStr).append(ReportingConstant.SEPARATOR_LS_SECOND);// 逾期日期
        sb.append(StringUtils.isNotBlank(amLoanAccountInfo.getLoanClassify()) ? iLSFileService.getICRCode("LOAN_CLASSIFY", amLoanAccountInfo.getLoanClassify()) : "1").append(ReportingConstant.SEPARATOR_LS_SECOND);// 五级分类
        sb.append(fiveCateAdjDate).append(ReportingConstant.SEPARATOR_LS_SECOND);// 五级分类认定日期
        sb.append(iLSFileService.getICRCode("ACCOUNT_STATUS", amLoanAccountInfo.getAccountStatus())).append(ReportingConstant.SEPARATOR_LS_SECOND);// 账户状态
        sb.append(amLoanAccountInfo.getPayoffDate()!=null ? DateUtils.format(amLoanAccountInfo.getPayoffDate(), DateUtils.DATE_PATTERN) : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 账户关闭日期
        sb.append(cmCustomerFirstLevel.getChineseName()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 借款人姓名
        sb.append("10").append(ReportingConstant.SEPARATOR_LS_SECOND);// 借款人证件类型 10-身份证 目前证件类型只有身份证
        sb.append(cmCustomerFirstLevel.getIdNumber()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 借款人证件号码
        sb.append(0).append(ReportingConstant.SEPARATOR_LS_SECOND);// 资产转让标志 0-未转让
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 业务申请地行政区划代码 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户用户编号 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作用户编号 空
        sb.append(DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 更新日期
        sb.append(DateUtils.format(amLoanAccountInfo.getCreateTime(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 数据日期 客户的登记日期
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段1 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段2 空
        sb.append("");// 扩展字段3 空
        return sb.toString();
    }

    /**
     * 生成个人合同信息
     *
     * @param loanId
     * @return String
     * @author liuyang
     * @date 2021-04-26
     */
    @Override
    public String createLSSecondContractFileMessage(String loanId) throws TxnBizException {

        logger.debug("临商二代征信个人合同信息文件生成，订单账户信息[{}]", loanId);

        AmLoanAccountInfo amLoanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanIdForBatch(loanId);

        AmLoanMainInfo amLoanMainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(amLoanAccountInfo.getLoanId(), amLoanAccountInfo.getTenantId());

        // 获取客户一级信息
        CmCustomerFirstLevel cmCustomerFirstLevel = customerService.getFirstLevelByCondition(amLoanMainInfo.getCustomerId(), amLoanMainInfo.getOrganizationId(), amLoanMainInfo.getTenantId());

        // 获取机构信息
        PrOrganizationTable organizationTable = organizationTableService.findByOrId(amLoanMainInfo.getOrganizationId(), amLoanMainInfo.getTenantId());

        // 五级分类认定日期
        String fiveCateAdjDate = DateUtils.format(amLoanMainInfo.getPostingDate(), DateUtils.DATE_PATTERN);
        TlLoanClassifyChange tlLoanClassifyChange = extTlLoanClassifyChangeMapper.selectLastByLoanId(amLoanAccountInfo.getTenantId(), amLoanAccountInfo.getCustomerId(), amLoanAccountInfo.getLoanId());
        if (tlLoanClassifyChange!=null) {
            fiveCateAdjDate = DateUtils.format(DateUtils.parseDate(tlLoanClassifyChange.getBusinessDate(), DateUtils.DATE_PATTERN_ANOTHER), DateUtils.DATE_PATTERN);
        }

        StringBuilder sb = new StringBuilder();
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(amLoanMainInfo.getContractId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 合同号
        sb.append(amLoanMainInfo.getCustomerId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 客户号
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(amLoanMainInfo.getContractId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 授信协议标识码
        sb.append("D1").append(ReportingConstant.SEPARATOR_LS_SECOND);// 账户类型 D1-非循环贷账户
        sb.append("0").append(ReportingConstant.SEPARATOR_LS_SECOND);// 分次放款标志 0-贷款额度一次性发放
        sb.append(cmCustomerFirstLevel.getChineseName()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 借款人姓名
        sb.append("10").append(ReportingConstant.SEPARATOR_LS_SECOND);// 借款人证件类型 10-身份证 目前证件类型只有身份证
        sb.append(cmCustomerFirstLevel.getIdNumber()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 借款人证件号码
        sb.append("1").append(ReportingConstant.SEPARATOR_LS_SECOND);// 借贷业务大类 1-贷款
        sb.append(iLSFileService.getICRCode("LOAN_TYPE", amLoanMainInfo.getLoanType())).append(ReportingConstant.SEPARATOR_LS_SECOND); // 借贷业务种类细分 41-个人经营性贷款, 91-其他个人消费贷款
        sb.append(DateUtils.format(amLoanMainInfo.getPostingDate(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 开户日期
        sb.append(amLoanMainInfo.getLastPaymentDate()==null ? "" : DateUtils.format(amLoanMainInfo.getLastPaymentDate(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 到期日期
        sb.append("CNY").append(ReportingConstant.SEPARATOR_LS_SECOND);// 币种
        sb.append(amLoanMainInfo.getLoanAmount()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 合同金额
        sb.append(amLoanAccountInfo.getRemainPrincipal()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 合同可用余额 合同本金余额
        sb.append(amLoanAccountInfo.getPayoffDate()!=null ? 2 : 1).append(ReportingConstant.SEPARATOR_LS_SECOND);// 合同状态 未结清：1-有效  已结清：2-到期/失效
        sb.append(amLoanAccountInfo.getPayoffDate()!=null ? DateUtils.format(amLoanAccountInfo.getPayoffDate(), DateUtils.DATE_PATTERN) : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 合同关闭日期 结清日期
        sb.append(3).append(ReportingConstant.SEPARATOR_LS_SECOND);// 担保方式 3-保证
        sb.append(9).append(ReportingConstant.SEPARATOR_LS_SECOND);// 其他还款保证方式 9-其他
        sb.append(StringUtils.isNotBlank(amLoanAccountInfo.getLoanClassify()) ? iLSFileService.getICRCode("LOAN_CLASSIFY", amLoanAccountInfo.getLoanClassify()) : "1").append(ReportingConstant.SEPARATOR_LS_SECOND);// 五级分类
        sb.append(fiveCateAdjDate).append(ReportingConstant.SEPARATOR_LS_SECOND);// 五级分类认定日期
        sb.append(1).append(ReportingConstant.SEPARATOR_LS_SECOND);// 贷款发放形式 1-新增
        sb.append(1).append(ReportingConstant.SEPARATOR_LS_SECOND);// 业务经营类型 1-自营
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 业务申请地行政区划代码 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 贷款合同编号 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 是否为首套住房贷款 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户用户编号 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作用户编号 空
        sb.append(DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 更新日期
        sb.append(DateUtils.format(amLoanAccountInfo.getCreateTime(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 数据日期 客户的登记日期
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段1 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段2 空
        sb.append("");// 扩展字段3 空
        return sb.toString();
    }

    /**
     * 生成还款计划
     *
     * @param planId
     * @return String
     * @author liuyang
     * @date 2021-04-26
     */
    @Override
    public String createLSSecondRepaymentFileMessage(Long planId) throws TxnBizException {

        logger.debug("临商二代征信还款计划文件生成，还款计划[{}]", planId);

        AmRepaymentPlanInfo amRepaymentPlanInfo = extAmRepaymentPlanInfoMapper.selectByPrimaryKey(planId);

        // 获取机构信息
        PrOrganizationTable organizationTable = organizationTableService.findByOrId(amRepaymentPlanInfo.getOrganizationId(), amRepaymentPlanInfo.getTenantId());

        // 宽限期计算
        AmLoanAccountInfo amLoanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanIdForBatch(amRepaymentPlanInfo.getLoanId());
        PrProductTable productTable = productTableService.findProByProIdAndOrgId(amRepaymentPlanInfo.getProductId(), amRepaymentPlanInfo.getOrganizationId(), amRepaymentPlanInfo.getTenantId());
        Integer graceDays = productTable.getGraceDays();
        //按订单计算 订单级宽限期，若往期处于逾期状态，则当期没有宽限期
        if (TransBizConstant.GRACE_OPTION_BY_LOAN.equals(productTable.getGraceOption()) &&
                TransBizConstant.LOAN_STATUS_2.equals(amLoanAccountInfo.getAccountStatus())) {
            graceDays = 0;
        }
        String graceDateStr = "";
        if (graceDays != null && graceDays > 0) {
            graceDateStr = DateUtils.format(DateUtils.addDay(amRepaymentPlanInfo.getPaymentDueDate(), graceDays), DateUtils.DATE_PATTERN);
        }

        // 应还本金罚息计算, 应还利息罚息计算
        BigDecimal penaltyAmt = BigDecimal.ZERO;
        BigDecimal compoundAmt = BigDecimal.ZERO;
        List<AmAccountMainInfo> amAccountMainInfos =
                extAmAccountMainInfoMapper.selectAccount(amRepaymentPlanInfo.getLoanId(),
                        amRepaymentPlanInfo.getCustomerId(), amRepaymentPlanInfo.getTenantId(),
                        Arrays.asList(TransBizConstant.ACCOUNT_TYPE_11, TransBizConstant.ACCOUNT_TYPE_12),
                        amRepaymentPlanInfo.getBillingTenor(), Arrays.asList(TransBizConstant.ACCOUNT_STATUS_1,
                                TransBizConstant.ACCOUNT_STATUS_2));
        List<AmInterestAccrualInfo> penaltyInterestAccrualInfos =
                extAmInterestAccrualInfoMapper.selectAccuAcct(amRepaymentPlanInfo.getLoanId(),
                        amRepaymentPlanInfo.getCustomerId(), amRepaymentPlanInfo.getTenantId(),
                        TransBizConstant.INTEREST_ACCRUAL_TYPE_10, amRepaymentPlanInfo.getBillingTenor(),
                        TransBizConstant.INTEREST_ACCRUAL_STATUS_1);
        List<AmInterestAccrualInfo> compoundInterestAccrualInfos =
                extAmInterestAccrualInfoMapper.selectAccuAcct(amRepaymentPlanInfo.getLoanId(),
                        amRepaymentPlanInfo.getCustomerId(), amRepaymentPlanInfo.getTenantId(),
                        TransBizConstant.INTEREST_ACCRUAL_TYPE_20, amRepaymentPlanInfo.getBillingTenor(),
                        TransBizConstant.INTEREST_ACCRUAL_STATUS_1);
        if (!CollectionUtils.isEmpty(amAccountMainInfos)) {
            penaltyAmt = penaltyAmt.add(amAccountMainInfos.stream().filter(e -> TransBizConstant.ACCOUNT_TYPE_11.equals(e.getAccountType()))
                    .map(AmAccountMainInfo::getCurrBalance).reduce(BigDecimal.ZERO, BigDecimal::add));
            compoundAmt = compoundAmt.add(amAccountMainInfos.stream().filter(e -> TransBizConstant.ACCOUNT_TYPE_12.equals(e.getAccountType()))
                    .map(AmAccountMainInfo::getCurrBalance).reduce(BigDecimal.ZERO, BigDecimal::add));
        }
        if (!CollectionUtils.isEmpty(penaltyInterestAccrualInfos)) {
            penaltyAmt = penaltyAmt.add(penaltyInterestAccrualInfos.stream().map(AmInterestAccrualInfo::getAccrualTotalAccruInterest).reduce(BigDecimal.ZERO,
                    BigDecimal::add));
        }
        if (!CollectionUtils.isEmpty(compoundInterestAccrualInfos)) {
            compoundAmt = compoundAmt.add(compoundInterestAccrualInfos.stream().map(AmInterestAccrualInfo::getAccrualTotalAccruInterest).reduce(BigDecimal.ZERO,
                    BigDecimal::add));
        }

        // 还款标志 0-已还清  1-未还清
        int payoffStatus = TransBizConstant.LOAN_PLAN_STATUS_7.equals(amRepaymentPlanInfo.getPlanStatus()) || TransBizConstant.LOAN_PLAN_STATUS_8.equals(amRepaymentPlanInfo.getPlanStatus()) ? 0 : 1;

        StringBuilder sb = new StringBuilder();
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(amRepaymentPlanInfo.getLoanId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 账户标识码
        sb.append(DateUtils.format(amRepaymentPlanInfo.getPaymentDueDate(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 结算日期
        sb.append(graceDateStr).append(ReportingConstant.SEPARATOR_LS_SECOND);// 宽限日期
        sb.append(amRepaymentPlanInfo.getPrincipalAmount() != null ? amRepaymentPlanInfo.getPrincipalAmount() : BigDecimal.ZERO).append(ReportingConstant.SEPARATOR_LS_SECOND);// 应还本金
        sb.append(amRepaymentPlanInfo.getInterestAmount() != null ? amRepaymentPlanInfo.getInterestAmount() : BigDecimal.ZERO).append(ReportingConstant.SEPARATOR_LS_SECOND);// 应还利息
        sb.append(penaltyAmt).append(ReportingConstant.SEPARATOR_LS_SECOND);// 应还本金罚息
        sb.append(compoundAmt).append(ReportingConstant.SEPARATOR_LS_SECOND);// 应还利息罚息
        sb.append(amRepaymentPlanInfo.getTransactionDate()!=null ? DateUtils.format(amRepaymentPlanInfo.getTransactionDate(), DateUtils.DATE_PATTERN) : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 实还日期
        sb.append(amRepaymentPlanInfo.getRepayPrincipal() != null ? amRepaymentPlanInfo.getRepayPrincipal() : BigDecimal.ZERO).append(ReportingConstant.SEPARATOR_LS_SECOND);// 实还本金
        sb.append(amRepaymentPlanInfo.getRepayInterest() != null ? amRepaymentPlanInfo.getRepayInterest() : BigDecimal.ZERO).append(ReportingConstant.SEPARATOR_LS_SECOND);// 实还利息
        sb.append(amRepaymentPlanInfo.getRepayPenaltyInterest() != null ? amRepaymentPlanInfo.getRepayPenaltyInterest() : BigDecimal.ZERO).append(ReportingConstant.SEPARATOR_LS_SECOND);// 实还本金罚息
        sb.append(amRepaymentPlanInfo.getRepayCompoundInterest() != null ? amRepaymentPlanInfo.getRepayCompoundInterest() : BigDecimal.ZERO).append(ReportingConstant.SEPARATOR_LS_SECOND);// 实还利息罚息
        sb.append(payoffStatus).append(ReportingConstant.SEPARATOR_LS_SECOND);// 还款标志
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户用户编号 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作用户编号 空
        sb.append(DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 更新日期
        sb.append(DateUtils.format(amRepaymentPlanInfo.getCreateTime(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 数据日期 客户的登记日期
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段1 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段2 空
        sb.append("");// 扩展字段3 空
        return sb.toString();
    }

    /**
     * 生成还款流水
     *
     * @param tlThirdPartyPayment
     * @return String
     * @author liuyang
     * @date 2021-04-26
     */
    @Override
    public String createLSSecondThirdPaymentFileMessage(TlThirdPartyPayment tlThirdPartyPayment) throws TxnBizException {

        logger.debug("临商二代征信还款流水文件生成，还款流水[{}]", tlThirdPartyPayment.getSeqNo());

        // 实还本金,实还利息,实还罚息,实还复利计算
        BigDecimal principalRepayAmt = BigDecimal.ZERO;
        BigDecimal interestRepayAmt = BigDecimal.ZERO;
        BigDecimal penaltyRepayAmt = BigDecimal.ZERO;
        BigDecimal compoundRepayAmt = BigDecimal.ZERO;
        List<TlPaymentAllocationLog> paymentAllocationLogs =
                extTlPaymentAllocationLogMapper.findCustLog(tlThirdPartyPayment.getLoanId(),
                        tlThirdPartyPayment.getSeqNo(), tlThirdPartyPayment.getCustomerId(),
                        tlThirdPartyPayment.getTenantId());
        if (!CollectionUtils.isEmpty(paymentAllocationLogs)) {
            principalRepayAmt = paymentAllocationLogs.stream().filter(log -> TransBizConstant.ACCOUNT_TYPE_06.equals(log.getConnectAccountType()))
                    .map(TlPaymentAllocationLog::getPostingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

            interestRepayAmt = paymentAllocationLogs.stream().filter(log -> TransBizConstant.ACCOUNT_TYPE_04.equals(log.getConnectAccountType()))
                    .map(TlPaymentAllocationLog::getPostingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

            penaltyRepayAmt = paymentAllocationLogs.stream().filter(log -> TransBizConstant.ACCOUNT_TYPE_11.equals(log.getConnectAccountType()))
                    .map(TlPaymentAllocationLog::getPostingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

            compoundRepayAmt = paymentAllocationLogs.stream().filter(log -> TransBizConstant.ACCOUNT_TYPE_12.equals(log.getConnectAccountType()))
                    .map(TlPaymentAllocationLog::getPostingAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }

        // 获取机构信息
        PrOrganizationTable organizationTable = organizationTableService.findByOrId(tlThirdPartyPayment.getOrganizationId(), tlThirdPartyPayment.getTenantId());

        StringBuilder sb = new StringBuilder();
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(tlThirdPartyPayment.getLoanId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 账户标识码
        sb.append(tlThirdPartyPayment.getSeqNo()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 还款流水号
        sb.append(tlThirdPartyPayment.getBusinessDate()!=null ? DateUtils.format(tlThirdPartyPayment.getBusinessDate(), DateUtils.DATE_PATTERN) : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 发生日期
        sb.append(principalRepayAmt).append(ReportingConstant.SEPARATOR_LS_SECOND);// 还款本金
        sb.append(interestRepayAmt).append(ReportingConstant.SEPARATOR_LS_SECOND);// 还款利息
        sb.append(penaltyRepayAmt).append(ReportingConstant.SEPARATOR_LS_SECOND);// 发生本金罚息
        sb.append(compoundRepayAmt).append(ReportingConstant.SEPARATOR_LS_SECOND);// 发生利息罚息
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户用户编号 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作用户编号 空
        sb.append(DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 更新日期
        sb.append(DateUtils.format(tlThirdPartyPayment.getCreateTime(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 数据日期 客户的登记日期
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段1 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段2 空
        sb.append("");// 扩展字段3 空
        return sb.toString();
    }

    /**
     * 生成特殊交易
     *
     * @param tlThirdPartyPayment
     * @return String
     * @author liuyang
     * @date 2021-04-26
     */
    @Override
    public String createLSSecondSpecialTranFileMessage(TlThirdPartyPayment tlThirdPartyPayment) throws TxnBizException {

        logger.debug("临商二代征信特殊交易文件生成，还款流水[{}]", tlThirdPartyPayment.getSeqNo());

        // 变更月数计算
        List<AmRepaymentPlanInfo> amRepaymentPlanInfos =
                extAmRepaymentPlanInfoMapper.selectByLoanIdAndStatus(tlThirdPartyPayment.getLoanId(), Arrays.asList(TransBizConstant.LOAN_PLAN_STATUS_7),
                        tlThirdPartyPayment.getCustomerId(), tlThirdPartyPayment.getTenantId());
        int changeMonths = CollectionUtils.isEmpty(amRepaymentPlanInfos) ? 0 : amRepaymentPlanInfos.size();

        // 获取机构信息
        PrOrganizationTable organizationTable = organizationTableService.findByOrId(tlThirdPartyPayment.getOrganizationId(), tlThirdPartyPayment.getTenantId());

        StringBuilder sb = new StringBuilder();
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(tlThirdPartyPayment.getLoanId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 账户标识码
        sb.append(tlThirdPartyPayment.getSeqNo()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 特殊交易标识码
        sb.append(5).append(ReportingConstant.SEPARATOR_LS_SECOND);// 交易类型 5-提前结清
        sb.append(tlThirdPartyPayment.getBusinessDate()!=null ? DateUtils.format(tlThirdPartyPayment.getBusinessDate(), DateUtils.DATE_PATTERN) : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 交易日期
        sb.append(tlThirdPartyPayment.getAmount()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 交易金额
        sb.append(changeMonths).append(ReportingConstant.SEPARATOR_LS_SECOND);// 到期日期变更月数
        sb.append("提前全部还款，还款月数变更" + changeMonths + "月,发生金额" + tlThirdPartyPayment.getAmount()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 交易明细信息
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户用户编号 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作用户编号 空
        sb.append(DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 更新日期
        sb.append(DateUtils.format(tlThirdPartyPayment.getCreateTime(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 数据日期 客户的登记日期
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段1 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段2 空
        sb.append("");// 扩展字段3 空
        return sb.toString();
    }

    /**
     * 生成个人信息
     *
     * @param cmCustomerFirstLevel
     * @return String
     * @author liuyang
     * @date 2021-04-26
     */
    @Override
    public String createLSSecondCustFileMessage(CmCustomerFirstLevel cmCustomerFirstLevel) throws TxnBizException {

        logger.debug("临商二代征信个人信息文件生成，客户id[{}]", cmCustomerFirstLevel.getCustomerId());

        // 根据日切结束时间获取最新的客户二级信息
        PrOrganizationTable organizationTable = organizationTableService.findByOrgIdForBatch(cmCustomerFirstLevel.getOrganizationId());
        BtBatchStatus statuses = extBtBatchStatusMapper.selectByStatusAndJobName(ReportingConstant.BATCH_SATTUS_2, ReportingConstant.CUTOVER_END,organizationTable.getTenantId(),organizationTable.getToday());
        Date updateTime = null;
        if(null != statuses){
            updateTime = statuses.getCreateTime();
        }
        try {
            // 判断是不是全量抽取日期，如果是则设置updateTime=null，进行全量抽取。
            SystemParameterRes systemParameterRes = systemParameterService.findByParamCode(ReportingConstant.REPORTING_ALL_DATE, organizationTable.getTenantId());
            String reportingAllDate = systemParameterRes!=null ? systemParameterRes.getParamValue() : "";
            String todayStr = DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN);
            if (todayStr.equals(reportingAllDate)){
                updateTime = null;
            }
        } catch (TxnException e) {
            logger.error("获取全量抽取日期异常：{}", e);
            throw new TxnRuntimeException(e.getErrCode(), e.getErrMsg());
        }

        // 查询需要征信报送的渠道id
        List<String> channelIds = extPrChannelTableMapper.selectByCreditReporting(cmCustomerFirstLevel.getTenantId(), ReportingConstant.YES_FLAG);

        // 多渠道客户，获取最新的客户二级信息
        CmCustomerSecondLevel cmCustomerSecondLevel = extCmCustomerSecondLevelMapper.selectByUpdateTimeAndCustId(cmCustomerFirstLevel.getTenantId(),cmCustomerFirstLevel.getCustomerId(), updateTime, channelIds);
        if (cmCustomerSecondLevel == null) {
            return null;
        }

        //获取客户地址信息
        List<CmCustomerAddressInfo> addressInfos = extCmCustomerAddressInfoMapper.selectByCustomerIdAndUpdateTime(cmCustomerSecondLevel.getTenantId(), cmCustomerSecondLevel.getCustomerId(),
                null, channelIds, null);

        String liveAddr = "未知"; // 居住地址
        String liveDistrict = ""; // 居住所在地行政区划
        String liveZipCode = "999999"; // 居住地址邮政编码
        String registerAddr = "未知"; // 户籍地址
        String registerDistrict = ""; // 户籍所在地行政区划
        String companyAddr = "未知"; // 单位地址
        String companyDistrict = ""; // 单位所在地行政区划
        String companyZipCode = "999999"; // 单位地址邮政编码
        if (!CollectionUtils.isEmpty(addressInfos)) {
            Optional<CmCustomerAddressInfo> customerAddressInfo =
                    addressInfos.stream().filter(e -> CustomerConstant.ADDRESS_TYPE_1.equals(e.getAddressType())).findFirst();
            if (customerAddressInfo.isPresent()) {
                // 居住地址
                liveAddr = iLSFileService.getAllAddress(customerAddressInfo.get());
                liveAddr = StringUtils.filterSpecialChar(liveAddr); // 过滤特殊字符
                liveAddr = iLSFileService.getLSLenStr(liveAddr, 200); // 地址字节长度不能超过200
                // 居住地址邮政编码
                liveZipCode = StringUtils.isNotBlank(customerAddressInfo.get().getZipcode()) ? customerAddressInfo.get().getZipcode() : "999999";
                // 居住所在地行政区划
                liveDistrict = StringUtils.isNotBlank(customerAddressInfo.get().getDistrict()) ? customerAddressInfo.get().getDistrict() : "";
            }

            // 户籍地址
            customerAddressInfo = addressInfos.stream().filter(e -> CustomerConstant.ADDRESS_TYPE_0.equals(e.getAddressType())).findFirst();
            if (customerAddressInfo.isPresent()) {
                registerAddr = iLSFileService.getAllAddress(customerAddressInfo.get());
                registerAddr = iLSFileService.getLSLenStr(registerAddr, 200);
                registerAddr = StringUtils.filterSpecialChar(registerAddr); // 过滤特殊字符
                registerDistrict = StringUtils.isNotBlank(customerAddressInfo.get().getDistrict()) ? customerAddressInfo.get().getDistrict() : "";
            }

            customerAddressInfo = addressInfos.stream().filter(e -> CustomerConstant.ADDRESS_TYPE_3.equals(e.getAddressType())).findFirst();
            if (customerAddressInfo.isPresent()) {
                // 单位地址
                companyAddr = iLSFileService.getAllAddress(customerAddressInfo.get());
                companyAddr = StringUtils.filterSpecialChar(companyAddr); // 过滤特殊字符
                companyAddr = iLSFileService.getLSLenStr(companyAddr, 200);
                // 单位地址邮政编码
                companyZipCode = StringUtils.isNotBlank(customerAddressInfo.get().getZipcode()) ? customerAddressInfo.get().getZipcode() : "999999";
                // 单位所在地行政区划
                companyDistrict = StringUtils.isNotBlank(customerAddressInfo.get().getDistrict()) ? customerAddressInfo.get().getDistrict() : "";
            }
        }

        // 证件有效到期日期
        String idExpireDate="";
        if (StringUtils.isNotBlank(cmCustomerFirstLevel.getIdExpireDate())) {
            idExpireDate = "长期".equals(cmCustomerFirstLevel.getIdExpireDate()) ? "2099-12-31" : cmCustomerFirstLevel.getIdExpireDate();
        } else if (StringUtils.isNotBlank(cmCustomerFirstLevel.getIdEffectiveDate())) {
            idExpireDate = "2099-12-31";
        }

        StringBuilder sb = new StringBuilder();
        sb.append(cmCustomerFirstLevel.getCustomerId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 客户号
        sb.append(cmCustomerFirstLevel.getChineseName()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 姓名
        sb.append("10").append(ReportingConstant.SEPARATOR_LS_SECOND);// 证件类型 10-身份证 目前证件类型只有身份证
        sb.append(cmCustomerFirstLevel.getIdNumber()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 证件号码
        sb.append(StringUtils.isNotBlank(cmCustomerFirstLevel.getIdEffectiveDate()) ? cmCustomerFirstLevel.getIdEffectiveDate() : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 证件有效期起始日期
        sb.append(idExpireDate).append(ReportingConstant.SEPARATOR_LS_SECOND);// 证件有效期到期日期
        sb.append(StringUtils.isNotBlank(cmCustomerFirstLevel.getIdIssueAgent()) ? iLSFileService.getLSLenStr(cmCustomerFirstLevel.getIdIssueAgent(), 160) : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 证件签发机关名称
        sb.append(cmCustomerFirstLevel.getIdNumber().substring(0, 6)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 证件签发机关所在地行政区划,取身份证号前6位
        sb.append(11).append(ReportingConstant.SEPARATOR_LS_SECOND);// 客户资料类型 11-贷款客户资料
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 信息来源编码
        sb.append(StringUtils.isNotBlank(cmCustomerFirstLevel.getSex()) ? cmCustomerFirstLevel.getSex() : "0").append(ReportingConstant.SEPARATOR_LS_SECOND);// 性别
        sb.append(cmCustomerFirstLevel.getBirthDate()==null ? "" : DateUtils.format(cmCustomerFirstLevel.getBirthDate(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 出生日期
        sb.append(991).append(ReportingConstant.SEPARATOR_LS_SECOND);// 国籍 991-中国
        sb.append(registerAddr).append(ReportingConstant.SEPARATOR_LS_SECOND);// 户籍地址
        sb.append(registerDistrict).append(ReportingConstant.SEPARATOR_LS_SECOND);// 户籍所在地行政区划
        sb.append(cmCustomerSecondLevel.getMobile()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 手机号码
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 电子邮箱
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getEducation()) ? iLSFileService.getICRCode("EDUCATION", cmCustomerSecondLevel.getEducation()) : "99").append(ReportingConstant.SEPARATOR_LS_SECOND);// 学历
        sb.append(9).append(ReportingConstant.SEPARATOR_LS_SECOND);// 学位 9-未知
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getCompanyName()) ? "91" : "99").append(ReportingConstant.SEPARATOR_LS_SECOND);// 就业状况 91-在职 99-未知
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getCompanyName()) ? iLSFileService.getLSLenStr(StringUtils.filterSpecialChar(cmCustomerSecondLevel.getCompanyName()), 160) : "未知").append(ReportingConstant.SEPARATOR_LS_SECOND);// 单位名称
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getCompanyAttribute()) ? iLSFileService.getICRCode("COMPANY_ATTRIBUTE", cmCustomerSecondLevel.getCompanyAttribute()) : "99").append(ReportingConstant.SEPARATOR_LS_SECOND);// 单位性质 99-未知
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getIndustry()) ? cmCustomerSecondLevel.getIndustry().substring(0, 1) : "9").append(ReportingConstant.SEPARATOR_LS_SECOND);// 单位所属行业 9-未知
        sb.append(companyAddr).append(ReportingConstant.SEPARATOR_LS_SECOND);// 单位详细地址
        sb.append(companyZipCode).append(ReportingConstant.SEPARATOR_LS_SECOND);// 单位所在地邮编
        sb.append(companyDistrict).append(ReportingConstant.SEPARATOR_LS_SECOND);// 单位所在地行政区划
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getCompanyPhone()) ? cmCustomerSecondLevel.getCompanyPhone() : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 单位电话
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getOccuptionType()) ? iLSFileService.getICRCode("OCCUPTION_TYPE", cmCustomerSecondLevel.getOccuptionType()) : "Z").append(ReportingConstant.SEPARATOR_LS_SECOND);// 职业 Z-未知
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getPosition()) ? iLSFileService.getICRCode("JOB_CODE", cmCustomerSecondLevel.getPosition()) : "9").append(ReportingConstant.SEPARATOR_LS_SECOND);// 职务 9-未知
        sb.append(9).append(ReportingConstant.SEPARATOR_LS_SECOND);// 职称
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 本单位工作起始年份
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getFamilyStatus()) ? iLSFileService.getICRCode("FAMILY_STATUS", cmCustomerSecondLevel.getFamilyStatus()) : "9").append(ReportingConstant.SEPARATOR_LS_SECOND);// 居住状况 9-未知
        sb.append(liveAddr).append(ReportingConstant.SEPARATOR_LS_SECOND);// 居住地详细地址
        sb.append(liveZipCode).append(ReportingConstant.SEPARATOR_LS_SECOND);// 居住地邮政编码
        sb.append(liveDistrict).append(ReportingConstant.SEPARATOR_LS_SECOND);// 居住地行政区划
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getHomePhone()) ? cmCustomerSecondLevel.getHomePhone() : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 住宅电话
        sb.append(liveAddr).append(ReportingConstant.SEPARATOR_LS_SECOND);// 通讯地址
        sb.append(liveZipCode).append(ReportingConstant.SEPARATOR_LS_SECOND);// 通讯地邮编
        sb.append(liveDistrict).append(ReportingConstant.SEPARATOR_LS_SECOND);// 通讯地行政区划
        sb.append(StringUtils.isNotBlank(cmCustomerSecondLevel.getMaritalStatus()) ? iLSFileService.getICRCode("MARITAL_STATUS", cmCustomerSecondLevel.getMaritalStatus()) : "99").append(ReportingConstant.SEPARATOR_LS_SECOND);// 婚姻状况 99-未知
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 自报年收入 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 缴税年收入 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户用户编号 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作用户编号 空
        sb.append(DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 更新日期
        sb.append(DateUtils.format(cmCustomerSecondLevel.getCreateTime(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 数据日期 客户的登记日期
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段1 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段2 空
        sb.append("");// 扩展字段3 空
        return sb.toString();
    }

    /**
     * 生成个人关联信息
     *
     * @param cmCustomerFirstLevel
     * @return List
     * @author liuyang
     * @date 2021-04-26
     */
    @Override
    public List<String> createLSSecondCustContactFileMessage(CmCustomerFirstLevel cmCustomerFirstLevel) throws TxnBizException {

        logger.debug("临商二代征信个人联系人信息文件生成，客户id[{}]", cmCustomerFirstLevel.getCustomerId());

        // 根据日切结束时间获取最新的客户联系人信息
        PrOrganizationTable organizationTable = organizationTableService.findByOrgIdForBatch(cmCustomerFirstLevel.getOrganizationId());
        BtBatchStatus statuses = extBtBatchStatusMapper.selectByStatusAndJobName(ReportingConstant.BATCH_SATTUS_2, ReportingConstant.CUTOVER_END,organizationTable.getTenantId(),organizationTable.getToday());
        Date updateTime = null;
        if(null != statuses){
            updateTime = statuses.getCreateTime();
        }
        try {
            // 判断是不是全量抽取日期，如果是则设置updateTime=null，进行全量抽取。
            SystemParameterRes systemParameterRes = systemParameterService.findByParamCode(ReportingConstant.REPORTING_ALL_DATE, organizationTable.getTenantId());
            String reportingAllDate = systemParameterRes!=null ? systemParameterRes.getParamValue() : "";
            String todayStr = DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN);
            if (todayStr.equals(reportingAllDate)) {
                updateTime = null;
            }
        } catch (TxnException e) {
            logger.error("获取全量抽取日期异常：{}", e);
            throw new TxnRuntimeException(e.getErrCode(), e.getErrMsg());
        }

        // 查询需要征信报送的渠道id
        List<String> channelIds = extPrChannelTableMapper.selectByCreditReporting(cmCustomerFirstLevel.getTenantId(), ReportingConstant.YES_FLAG);

        List<CmCustomerContactInfo> cmCustomerContactInfos = extCmCustomerContactInfoMapper.selectByCustomerIdAndUpdateTime(cmCustomerFirstLevel.getTenantId(), cmCustomerFirstLevel.getCustomerId(), updateTime, channelIds, null);
        if (CollectionUtils.isEmpty(cmCustomerContactInfos)) {
            return null;
        }

        Set<String> relationships = new HashSet<>(); // 联系人关系
        List<String> resList = new ArrayList<>();

        for (CmCustomerContactInfo cmCustomerContactInfo : cmCustomerContactInfos) {
            // 多渠道的客户，每一种关系的联系人取当期最新的
            if (relationships.contains(cmCustomerContactInfo.getRelationship())) {
                continue;
            }
            relationships.add(cmCustomerContactInfo.getRelationship());

            // 配偶才采集手机号，工作单位
            String mobile = "";
            String companyName = "";
            if (CustomerConstant.CONTACT_TYPE_01.equals(cmCustomerContactInfo.getRelationship()) && ReportingConstant.YES_FLAG.equals(cmCustomerContactInfo.getContactStatus())) {
                mobile = StringUtils.isNotBlank(cmCustomerContactInfo.getMobile()) ? cmCustomerContactInfo.getMobile() : "";
                companyName = StringUtils.filterSpecialChar(cmCustomerContactInfo.getCompanyName());
                companyName = iLSFileService.getLSLenStr(companyName, 160);
            }

            StringBuilder sb = new StringBuilder();
            sb.append(cmCustomerContactInfo.getCustomerId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 客户号
            sb.append(cmCustomerContactInfo.getId()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 关联序号
            sb.append(StringUtils.isNotBlank(cmCustomerContactInfo.getRelationship()) ? iLSFileService.getICRCode("RELATION", cmCustomerContactInfo.getRelationship()) : "8").append(ReportingConstant.SEPARATOR_LS_SECOND);// 关系类型
            sb.append(cmCustomerContactInfo.getChineseName()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 关系人姓名
            sb.append(StringUtils.isNotBlank(cmCustomerContactInfo.getIdType()) ? "10" : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 关系人证件类型
            sb.append(StringUtils.isNotBlank(cmCustomerContactInfo.getIdNumber()) ? cmCustomerContactInfo.getIdNumber() : "").append(ReportingConstant.SEPARATOR_LS_SECOND);// 关系人证件号码
            sb.append(mobile).append(ReportingConstant.SEPARATOR_LS_SECOND);// 关系人联系电话
            sb.append(companyName).append(ReportingConstant.SEPARATOR_LS_SECOND);// 关系人工作单位
            sb.append(cmCustomerContactInfo.getContactStatus()).append(ReportingConstant.SEPARATOR_LS_SECOND);// 有效标志
            sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户机构编号
            sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户用户编号 空
            sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作机构编号
            sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作用户编号 空
            sb.append(DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 更新日期
            sb.append(DateUtils.format(cmCustomerContactInfo.getCreateTime(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 数据日期
            sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段1 空
            sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段2 空
            sb.append("");// 扩展字段3 空
            resList.add(sb.toString());
        }
        return resList;
    }
    /**
     * 个人相关还款责任人信息
     *
     * @param loanId
     * @return String
     * @author liuyang
     * @date 2021-04-26
     */
    @Override
    public String createLSSecondRltRepymtInfoFileMessage(String loanId) throws TxnBizException {

        logger.debug("临商二代征信个人相关还款责任人信息文件生成，订单账户信息[{}]", loanId);

        // 订单信息
        AmLoanAccountInfo amLoanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanIdForBatch(loanId);
        // 订单账户信息
        AmLoanMainInfo amLoanMainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(amLoanAccountInfo.getLoanId(), amLoanAccountInfo.getTenantId());
        // 机构信息
        PrOrganizationTable organizationTable = organizationTableService.findByOrId(amLoanMainInfo.getOrganizationId(), amLoanMainInfo.getTenantId());

        // 还款责任金额
        BigDecimal arlpAmt = amLoanAccountInfo.getRemainPrincipal().multiply(new BigDecimal("0.2")).setScale(TransBizConstant.BIGDECIMAL_SCALE, BigDecimal.ROUND_HALF_UP);

        StringBuilder sb = new StringBuilder();
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(amLoanMainInfo.getContractId()).append(ReportingConstant.SEPARATOR_LS_SECOND);//账户标识码
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(amLoanMainInfo.getContractNumber()).append(ReportingConstant.SEPARATOR_LS_SECOND);//关联编号 普惠二期上线之前送外部合同号，普惠二期上线之后送保证合同编号
        sb.append(2).append(ReportingConstant.SEPARATOR_LS_SECOND);//身份类别 2-组织机构
        sb.append(ReportingConstant.PAPH_GUARANTEE_COMPANY).append(ReportingConstant.SEPARATOR_LS_SECOND);//责任人名称
        sb.append(20).append(ReportingConstant.SEPARATOR_LS_SECOND);//责任人身份标识类型 20-统一社会信用代码
        sb.append(ReportingConstant.PAPH_GUARANTEE_COMPANY_SOCIAL_CODE).append(ReportingConstant.SEPARATOR_LS_SECOND);//责任人身份标识号码
        sb.append(2).append(ReportingConstant.SEPARATOR_LS_SECOND);//还款责任人类型 2-保证人
        sb.append(arlpAmt).append(ReportingConstant.SEPARATOR_LS_SECOND);//还款责任金额 总欠款（本金+利息+罚息+复利）x 0.2
        sb.append(0).append(ReportingConstant.SEPARATOR_LS_SECOND);//联保标志 0-单人保证/多人分保
        sb.append(ReportingConstant.LS_ZX_ORGID).append(ReportingConstant.FIELD_PRE_LS).append(amLoanMainInfo.getContractNumber()).append(ReportingConstant.SEPARATOR_LS_SECOND);//保证合同编号 普惠二期上线之前送外部合同号，普惠二期上线之后送保证合同编号
        sb.append(1).append(ReportingConstant.SEPARATOR_LS_SECOND);//有效标志 1-有效
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 管户用户编号 空
        sb.append(ReportingConstant.LS_TIANJIN_ZX_ORGID).append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作机构编号
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 操作用户编号 空
        sb.append(DateUtils.format(organizationTable.getToday(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 更新日期
        sb.append(DateUtils.format(amLoanAccountInfo.getCreateTime(), DateUtils.DATE_PATTERN)).append(ReportingConstant.SEPARATOR_LS_SECOND);// 数据日期
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段1 空
        sb.append("").append(ReportingConstant.SEPARATOR_LS_SECOND);// 扩展字段2 空
        sb.append("");// 扩展字段3 空
        return sb.toString();
    }

    /**
     * 临商二代征信文件合并
     *
     * @param sourcePath
     * @param outPath
     * @throws TxnException
     * @author liuyang
     * @date 2021-05-07
     */
    @Override
    public void mergeLSSecondFile(String sourcePath, String outPath) throws TxnException {

        // 查询机构信息
        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(ReportingConstant.DEFAULT_ORG_NUMBER);
        String toDay = DateUtils.format(org.getToday(), DateUtils.DATE_PATTERN_ANOTHER);

        // 源文件目录
        StringBuilder sourceDirPathSb = new StringBuilder();
        sourceDirPathSb.append(sourcePath).append(File.separator).append(org.getTenantId()).append(File.separator).append(toDay);
        String sourceDirPath = sourceDirPathSb.toString();

        // 源文件列表
        List<String> fileNames = FileUtils.findFileNames(sourceDirPath);
        if (CollectionUtils.isEmpty(fileNames)) {
            logger.error("临商二代征信文件目录[{}]下没有文件。", sourceDirPath);
            throw new TxnException("临商二代征信文件目录[" + sourceDirPath + "]下没有文件");
        }

        // 合并文件目录
        StringBuilder outDirPathSb = new StringBuilder();
        outDirPathSb.append(outPath).append(File.separator).append(org.getTenantId()).append(File.separator).append(toDay);
        String outDirPath = outDirPathSb.toString();

        // 个人基本信息合并
        iLSFileService.mergeFile(ReportingConstant.LS_SECOND_FILE_INDINFO, toDay, sourceDirPath, outDirPath, fileNames, ReportingConstant.LS_SECOND_FILE_SUFFIX);

        // 个人关联信息合并
        iLSFileService.mergeFile(ReportingConstant.LS_SECOND_FILE_RELTINFO, toDay, sourceDirPath, outDirPath, fileNames, ReportingConstant.LS_SECOND_FILE_SUFFIX);

        //个人借据信息合并
        iLSFileService.mergeFile(ReportingConstant.LS_SECOND_FILE_ACCTINFO, toDay, sourceDirPath, outDirPath, fileNames, ReportingConstant.LS_SECOND_FILE_SUFFIX);

        //个人合同信息合并
        iLSFileService.mergeFile(ReportingConstant.LS_SECOND_FILE_ACCTCTRCT, toDay, sourceDirPath, outDirPath, fileNames, ReportingConstant.LS_SECOND_FILE_SUFFIX);

        //个人相关还款责任人信息合并
        iLSFileService.mergeFile(ReportingConstant.LS_SECOND_FILE_RLTREPYMTINFO, toDay, sourceDirPath, outDirPath, fileNames, ReportingConstant.LS_SECOND_FILE_SUFFIX);

        // 个人还款计划合并
        iLSFileService.mergeFile(ReportingConstant.LS_SECOND_FILE_PAYPLAN, toDay, sourceDirPath, outDirPath, fileNames, ReportingConstant.LS_SECOND_FILE_SUFFIX);

        // 个人还款流水合并
        iLSFileService.mergeFile(ReportingConstant.LS_SECOND_FILE_LCBACKLIST, toDay, sourceDirPath, outDirPath, fileNames, ReportingConstant.LS_SECOND_FILE_SUFFIX);

        // 个人特殊交易信息合并
        iLSFileService.mergeFile(ReportingConstant.LS_SECOND_FILE_SPECIBUSINESS, toDay, sourceDirPath, outDirPath, fileNames, ReportingConstant.LS_SECOND_FILE_SUFFIX);

        // 生成抵质押空文件 （无此场景的生成对应的空文件）
        // 个人抵质押关联信息表
        StringBuilder motgarltFilePathSb = new StringBuilder(outDirPath).append(File.separator).append(ReportingConstant.LS_SECOND_FILE_MOTGARLT).append(toDay).append(ReportingConstant.LS_SECOND_FILE_SUFFIX);
        FileUtils.createFile(motgarltFilePathSb.toString());
        // 抵质押合同信息表
        StringBuilder motgactrctFilePathSb = new StringBuilder(outDirPath).append(File.separator).append(ReportingConstant.LS_SECOND_FILE_MOTGACTRCT).append(toDay).append(ReportingConstant.LS_SECOND_FILE_SUFFIX);
        FileUtils.createFile(motgactrctFilePathSb.toString());
        // 抵押物信息表
        StringBuilder proptinfoFilePathSb = new StringBuilder(outDirPath).append(File.separator).append(ReportingConstant.LS_SECOND_FILE_PROPTINFO).append(toDay).append(ReportingConstant.LS_SECOND_FILE_SUFFIX);
        FileUtils.createFile(proptinfoFilePathSb.toString());
        //质物信息表
        StringBuilder cltalinfoFilePathSb = new StringBuilder(outDirPath).append(File.separator).append(ReportingConstant.LS_SECOND_FILE_CLTALINFO).append(toDay).append(ReportingConstant.LS_SECOND_FILE_SUFFIX);
        FileUtils.createFile(cltalinfoFilePathSb.toString());

        // 生成ok文件
        StringBuilder okFileNameSb = new StringBuilder();
        okFileNameSb.append(ReportingConstant.FILE_PRE_LS).append("_").append(toDay).append(".ok");
        String okFileName = okFileNameSb.toString();
        StringBuilder okFilePathSb = new StringBuilder();
        okFilePathSb.append(outDirPath).append(File.separator).append(okFileName);
        String okFilePath = okFilePathSb.toString();
        FileUtils.createFile(okFilePath);
    }
}